﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ServiceFactory.cs" company="">
//   
// </copyright>
// <summary>
//   The service factory.
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace F5.BigIp.LocalTrafficManager.Proxy.V11
{
    using System;
    using System.Security.Authentication.ExtendedProtection;
    using System.ServiceModel;

    using F5.BigIp.LocalTrafficManager.Interfaces;
    using F5.BigIp.LocalTrafficManager.Proxy.V11.LocalLB.Pool;
    using F5.BigIp.LocalTrafficManager.Proxy.V11.LocalLB.PoolMember;
    using F5.BigIp.LocalTrafficManager.Proxy.V11.SystemInfo;

    /// <summary>
    ///     The service factory.
    /// </summary>
    internal static class ServiceFactory
    {
        #region Constants

        /// <summary>
        ///     The web service url.
        /// </summary>
        private const string WebServiceUrl = "https://{0}/iControl/iControlPortal.cgi";

        #endregion

        #region Methods

        /// <summary>The create pool member service.</summary>
        /// <param name="loadBalancer">The LoadBalancer.</param>
        /// <returns>The <see cref="LocalLBPoolMemberPortTypeClient"/>.</returns>
        /// <exception cref="Exception">Endpoint configuration error. Service client credentials is null.</exception>
        internal static LocalLBPoolMemberPortType CreatePoolMemberService(LoadBalancer loadBalancer)
        {
            return CreateChannel<LocalLBPoolMemberPortType>(loadBalancer.Host, loadBalancer.UserName, loadBalancer.Password);
        }

        /// <summary>The create pool service.</summary>
        /// <param name="loadBalancer">The LoadBalancer.</param>
        /// <returns>The <see cref="LocalLBPoolPortTypeClient"/>.</returns>
        /// <exception cref="Exception">Endpoint configuration error. Service client credentials is null.</exception>
        internal static LocalLBPoolPortType CreatePoolService(LoadBalancer loadBalancer)
        {
            return CreateChannel<LocalLBPoolPortType>(loadBalancer.Host, loadBalancer.UserName, loadBalancer.Password);
        }

        /// <summary>The create system service.</summary>
        /// <param name="loadBalancer">The LoadBalancer.</param>
        /// <returns>The <see cref="SystemSystemInfoPortTypeClient"/>.</returns>
        /// <exception cref="Exception">Endpoint configuration error. Service client credentials is null.</exception>
        internal static SystemSystemInfoPortType CreateSystemInfoService(LoadBalancer loadBalancer)
        {
            return CreateChannel<SystemSystemInfoPortType>(loadBalancer.Host, loadBalancer.UserName, loadBalancer.Password);
        }

        /// <summary>The create channel.</summary>
        /// <param name="host">The host.</param>
        /// <param name="userName">The user name.</param>
        /// <param name="password">The password.</param>
        /// <typeparam name="T">The interface.</typeparam>
        /// <returns>The <see cref="T"/>.</returns>
        private static T CreateChannel<T>(string host, string userName, string password)
        {
            var binding = new BasicHttpBinding
                              {
                                  MaxBufferSize = 2147483647,
                                  MaxReceivedMessageSize = 2147483647,
                                  Security = new BasicHttpSecurity
                                          {
                                              Mode = BasicHttpSecurityMode.Transport,
                                              Transport = new HttpTransportSecurity
                                                      {
                                                          ClientCredentialType = HttpClientCredentialType.Basic,
                                                          ProxyCredentialType = HttpProxyCredentialType.Basic,
                                                          ExtendedProtectionPolicy = new ExtendedProtectionPolicy(PolicyEnforcement.Never)
                                                      }
                                          }
                              };

            string address = string.Format(WebServiceUrl, host);

            var endpointAddress = new EndpointAddress(address);

            var channelFactory = new ChannelFactory<T>(binding, endpointAddress);

            if (channelFactory.Credentials != null)
            {
                channelFactory.Credentials.UserName.UserName = userName;
                channelFactory.Credentials.UserName.Password = password;
            }

            return channelFactory.CreateChannel();
        }

        #endregion
    }
}